package com.huantai.common.util;

import java.math.RoundingMode;

import com.google.common.math.IntMath;
import com.google.common.math.LongMath;

/**
 * 
 * 数学相关工具类
 * 
 * @author Ma Chao
 * @version 2018年6月8日 上午9:00:51
 */
public final class MathUtil {
    /** 不允许使用对象来调用工具类的方法 */
    private MathUtil() {}

    /**
     * 是否2的倍数
     * 
     * @param value 不是正数时总是返回false
     */
    public static boolean isPowerOfTwo(int value) {
        return IntMath.isPowerOfTwo(value);
    }

    /**
     * 当模为2的倍数时，用比取模块更快的方式计算.
     * 
     * @param value 可以为负数，比如 －1 mod 16 = 15
     */
    public static int modByPowerOfTwo(int value, int mod) {
        return value & (mod - 1);
    }

    /**
     * 保证结果为正数的取模.
     * 
     * 如果(v = x/m) <0，v+=m.
     */
    public static int mod(int x, int m) {
        return IntMath.mod(x, m);
    }

    /**
     * 保证结果为正数的取模.
     * 
     * 如果(v = x/m) <0，v+=m.
     */
    public static long mod(long x, long m) {
        return LongMath.mod(x, m);
    }

    /**
     * 保证结果为正数的取模
     */
    public static int mod(long x, int m) {
        return LongMath.mod(x, m);
    }

    /**
     * 能控制rounding方向的int相除.
     * 
     * jdk的'/'运算符，直接向下取整
     */
    public static int divide(int p, int q, RoundingMode mode) {
        return IntMath.divide(p, q, mode);
    }

    /**
     * 能控制rounding方向的long相除
     * 
     * jdk的'/'运算符，直接向下取整
     */
    public static long divide(long p, long q, RoundingMode mode) {
        return LongMath.divide(p, q, mode);
    }

    /**
     * 平方
     * 
     * @param k 平方次数, 不能为负数, k=0时返回1.
     */
    public static int pow(int b, int k) {
        return IntMath.pow(b, k);
    }

    /**
     * 平方
     * 
     * @param k 平方次数,不能为负数, k=0时返回1.
     */
    public static long pow(long b, int k) {
        return LongMath.pow(b, k);
    }

    /**
     * 开方
     */
    public static int sqrt(int x, RoundingMode mode) {
        return IntMath.sqrt(x, mode);
    }

    /**
     * 开方
     */
    public static long sqrt(long x, RoundingMode mode) {
        return LongMath.sqrt(x, mode);
    }
}
